parser grammar PL00Parser;

options {
	tokenVocab=PL00Lexer;
}

program: importstmt* block DOT;

importstmt:
	Import path (COMMA path)* SEMICOLON;

path:
	Identifier (DIV Identifier)*;

block: consts? vars? (procedure | functionDef)* statement;

functionDefs: functionDef*;

consts:
	Const ident EQUAL (integer | real | string) (
		COMMA ident EQUAL (integer | real | string))* SEMICOLON;

vars: Var (ident (COMMA ident)* COLON type SEMICOLON)+;

procedure: Procedure ident SEMICOLON block SEMICOLON;

functionDef:
	Function Identifier LPAREN (ident COLON type (COMMA ident COLON type)*)? RPAREN COLON type SEMICOLON block SEMICOLON;

statement: (
		assignstmt
		| vectorassignstmt
		| callstmt
		| beginstmt
		| ifstmt
		| whilestmt
        | breakstmt
		| continuestmt
		| returnstmt
		| expression
	)?;

assignstmt: ident BECOMES expression;

vectorassignstmt:
	ident LBRACKET expression RBRACKET BECOMES expression;

callstmt: Call ident;

beginstmt: Begin statement (SEMICOLON statement)* End;

ifstmt: If condition Then statement ( Else statement )?;

whilestmt: While condition Do statement;

breakstmt: Break;

continuestmt: Continue;

returnstmt: Return expression;

condition:
	expression (EQUAL | NOTEQUAL | LT | LE | GT | GE) expression;

callfunction:
	Identifier LPAREN (expression (COMMA expression)*)? RPAREN;

expression: (PLUS | MINUS)? term ((PLUS | MINUS) term)*;

term: factor ((MUL | DIV) factor)*;

factor:
	ident # IdentFactor
	| integer # IntegerFactor
	| real # RealFactor
	| string # StringFactor
	| LPAREN expression RPAREN # BracketExpr
	| callfunction # FunctionCall
	| factor DOT callfunction # FunctionChain
	| factor LBRACKET expression RBRACKET # Index
	;

type: Identifier;

ident: Identifier;

integer: Integer;

real: Integer DOT Integer;

string: String;
